-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support InMemoryCache
field policy drop
functions, to allow cleanup when fields are removed from the cache
#8078
base: main
Are you sure you want to change the base?
Conversation
61d5bd4
to
8948dae
Compare
InMemoryCache
field policy finalize
functions, to allow cleanup when fields are removed from the cacheInMemoryCache
field policy drop
functions, to allow cleanup when fields are removed from the cache
As I described in this comment, though I decided to call the new function `drop` instead of `finalize`: #8052 (comment)
de99635
to
640d504
Compare
cache.writeQuery({ | ||
query, | ||
overwrite: true, | ||
data: { | ||
garbages: [ | ||
{ __typename: "Garbage", gid: 123, isToxic: false }, | ||
{ __typename: "Garbage", gid: 345, isToxic: true }, | ||
], | ||
}, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
}); | ||
}); | ||
|
||
itAsync("are called for fields within garbage collected objects", (resolve, reject) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of the low/central level where I'm enforcing the calling of drop
functions, any process that uses the EntityStore
API to delete fields (or the objects that contain them) will trigger the appropriate drop
functions. Even cache.gc()
triggers drop
functions. Pretty cool!
context.store.getStorage( | ||
isReference(objectOrReference) | ||
? objectOrReference.__ref | ||
: objectOrReference, | ||
storeFieldName, | ||
), | ||
(context.store as EntityStore).group | ||
.getStorage(objectOrReference, storeFieldName), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These context.store.group.getStorage
changes are not directly related to the goals of this PR, but are necessary to ensure the same storage
object gets passed in the options for read
, merge
, and drop
functions (assuming the underlying field is the same, of course). This is important so that (for example) drop
can always clean up the same storage
object previously populated by read
or merge
.
Implementation-wise, thanks to the assignPaths
method above, unidentifiable/non-normalized objects are now able to use group.getStorage
to look up the appropriate storage
object using the string ID of the enclosing entity object, together with a path of properties leading to the object within the entity. By relying on permanent strings rather than temporary object references as lookup keys, this approach makes storage
objects more stable for fields within non-normalized objects.
By contrast, for fields within normalized objects, the objectOrReference
variable here will always be a Reference
, which makes it easier to get the string ID directly from that Reference
object. In other words, storage
for fields within normalized objects was already "stable" in the sense used above, prior to this PR.
Something I haven't figured out yet: the best way to make sure |
Hi @benjamn, |
As I described in these comments, we recommend using the
storage
object for sharing private data betweenread
andmerge
(andmodify
) functions, but there's currently no good way to make sure thestorage
object gets cleaned up when the field is removed from the cache.This PR makes it possible to define a custom
drop
function for any field that needs special cleanup handling:The terminology offinalize
comes from the existing OOP concept of a finalizer that runs before an object is garbage collected, though I decided to avoid the nounfinalizer
in favor of the present-tense transitive verbfinalize
, to matchread
andmerge
.Edit: I decided to call this function
drop
instead offinalize
, partly for brevity, partly inspired by Rust, but also because a finalizer (in the OOP sense) typically runs for a whole object, whereas these field policydrop
functions run for specific fields.